package com.plugin.activity.sample

import android.content.Context
import android.content.Context.MODE_PRIVATE
import android.content.res.AssetManager
import android.content.res.Resources
import android.os.Environment
import android.util.Log
import android.widget.Toast

import dalvik.system.DexClassLoader
import java.io.File
import java.lang.Exception
import java.lang.reflect.Method


class PluginManager {

    companion object {
        private var INSTANCE: PluginManager? = null
        fun getInstance(): PluginManager =
            INSTANCE ?: synchronized(PluginManager::class) {
                INSTANCE ?: PluginManager().also { INSTANCE = it }
            }
    }

    private var dexClassLoader: DexClassLoader? = null
    private var resources: Resources? = null

    /**
     * （2.1 Activity class，  2.2layout）
     * 加载插件
     */
    fun loadPlugin(context: Context?) {
        try {
            val file =
                File(context?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)!!.absolutePath + File.separator.toString() + "p.apk")
            if(!file.exists()) {
                Toast.makeText(context,"插件包 不存在...",Toast.LENGTH_SHORT).show()
                return
            }
            val pluginPaht: String = file.absolutePath

            /**
             * 下面是加载插件里面的 class
             */

            // dexClassLoader需要一个缓存目录   /data/data/当前应用的包名/pDir
            val fileDir: File = context.getDir("dex", MODE_PRIVATE)

            // Activity class
            dexClassLoader = DexClassLoader(
                pluginPaht,
                fileDir.absolutePath,
                null,
                context.classLoader
            )
            /**
             * 下面是加载插件里面的layout
             */
            // 加载资源
            val assetManager = AssetManager::class.java.newInstance()

            // 我们要执行此方法，为了把插件包的路径 添加进去
            // public final int addAssetPath(String path)
            val addAssetPathMethod: Method =
                assetManager.javaClass.getMethod("addAssetPath", String::class.java) // 他是类类型 Class
            addAssetPathMethod.isAccessible = true
            addAssetPathMethod.invoke(assetManager, pluginPaht) // 插件包的路径   pluginPaht
            val r: Resources = context.resources // 宿主的资源配置信息

            // 特殊的 Resources，加载插件里面的资源的 Resources
            resources = Resources(
                assetManager,
                r.displayMetrics,
                r.configuration
            ) // 参数2 3  资源配置信息
        } catch(e: Exception) {
            e.printStackTrace()
        }
    }

    fun getClassLoader(): ClassLoader? {
        return dexClassLoader
    }

    fun getResources(): Resources? {
        return resources
    }

}